/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

package com.huawei.demo;

import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.http.HttpConfig;
import com.huaweicloud.sdk.ugo.v1.UgoClient;
import com.huaweicloud.sdk.ugo.v1.model.ConfirmTargetDBReq;
import com.huaweicloud.sdk.ugo.v1.model.ConfirmTargetDbTypeRequest;
import com.huaweicloud.sdk.ugo.v1.model.CreateEvaluationProjectReq;
import com.huaweicloud.sdk.ugo.v1.model.CreateEvaluationProjectRequest;
import com.huaweicloud.sdk.ugo.v1.model.DeleteEvaluationProjectRequest;
import com.huaweicloud.sdk.ugo.v1.model.EvaluationProject;
import com.huaweicloud.sdk.ugo.v1.model.ListEvaluationProjectsRequest;
import com.huaweicloud.sdk.ugo.v1.model.ListEvaluationProjectsResponse;
import com.huaweicloud.sdk.ugo.v1.model.ObjectTypeInfo;
import com.huaweicloud.sdk.ugo.v1.model.ProjectStatusDetail;
import com.huaweicloud.sdk.ugo.v1.model.SchemaInfo;
import com.huaweicloud.sdk.ugo.v1.model.ShowEvaluationProjectDetailRequest;
import com.huaweicloud.sdk.ugo.v1.model.ShowEvaluationProjectStatusRequest;
import com.huaweicloud.sdk.ugo.v1.model.ShowEvaluationProjectStatusResponse;
import com.huaweicloud.sdk.ugo.v1.model.SourceDBInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 数据库和应用迁移 UGO的示例代码：数据库评估
 *
 * @since 2022-08-20
 */
public class EvaluationProjectDemo {

    private static final Logger logger = LoggerFactory.getLogger(EvaluationProjectDemo.class);

    public static void main(String[] args) throws Exception {

        UgoClient ugoClient = getUgoClient();

        String evaluationProjectName = "<YOUR EVALUATION PROJECT NAME>";
        String sourceDbUserName = "<YOUR ORACLE SOURCE DATABASE USERNAME>";
        String sourceDbPassword = "<YOUR ORACLE SOURCE DATABASE PASSWORD>";
        String sourceDbConnectionString = "<YOUR ORACLE SOURCE DATABASE CONNECTION STRING>";
        String targetDBType = "RDS for MySQL";
        String targetDBVersion = "5.7";

        SourceDBInfo sourceDbInfo = new SourceDBInfo();
        sourceDbInfo.setUserName(sourceDbUserName);
        sourceDbInfo.setPassword(sourceDbPassword);
        sourceDbInfo.setSourceDbType(SourceDBInfo.SourceDbTypeEnum.ORACLE);
        sourceDbInfo.setSourceDbVersion(SourceDBInfo.SourceDbVersionEnum._11G);
        sourceDbInfo.setConnectionString(sourceDbConnectionString);

        // Step 1: Create ugo evaluation project.
        createEvaluationProject(ugoClient, evaluationProjectName, sourceDbInfo);

        // Step 2: Get evaluation project list.
        Integer evaluationProjectId = getEvaluationProjectId(ugoClient, evaluationProjectName);

        // Step 3: Check evaluation project status.
        checkEvaluationProjectStatus(ugoClient, evaluationProjectId);

        // Step 4: Confirm target db type.
        confirmTargetDBType(ugoClient, evaluationProjectId, targetDBType, targetDBVersion);

        // Step 5: Get evaluation project detail.
        getEvaluationProjectDetail(ugoClient, evaluationProjectId);

        // Step 6: Create migration project by this evaluation project.

        // Step 7: Delete evaluation project.
        deleteEvaluationProject(ugoClient, evaluationProjectId);

    }

    private static UgoClient getUgoClient() {
        String ak = "<YOUR AK>";
        String sk = "<YOUR SK>";
        String endpoint = "<YOUR ENDPOINT>";
        String projectId = "<YOUR PROJECTID>";

        // Http Configuration for client
        HttpConfig config = HttpConfig.getDefaultHttpConfig();
        config.withIgnoreSSLVerification(true);

        // Create the authentication
        BasicCredentials auth = new BasicCredentials()
                .withAk(ak)
                .withSk(sk)
                .withProjectId(projectId);

        // Create UgoClient instance
        return UgoClient.newBuilder()
                .withHttpConfig(config)
                .withCredential(auth)
                .withEndpoint(endpoint)
                .build();
    }

    private static void createEvaluationProject(UgoClient ugoClient, String evaluationProjectName, SourceDBInfo sourceDbInfo) {
        CreateEvaluationProjectRequest createEvaluationProjectRequest = new CreateEvaluationProjectRequest();
        CreateEvaluationProjectReq createEvaluationProjectBody = new CreateEvaluationProjectReq();
        createEvaluationProjectBody.setEvaluationProjectName(evaluationProjectName);
        createEvaluationProjectBody.setSourceDbInfo(sourceDbInfo);
        SchemaInfo schemasInfo = new SchemaInfo();
        schemasInfo.setIsSelectAllSchemas(Boolean.TRUE);
        createEvaluationProjectBody.setSchemasInfo(schemasInfo);
        ObjectTypeInfo objectsTypeInfo = new ObjectTypeInfo();
        objectsTypeInfo.setIsSelectAllObjectsType(Boolean.TRUE);
        createEvaluationProjectBody.setObjectsTypeInfo(objectsTypeInfo);
        createEvaluationProjectRequest.setBody(createEvaluationProjectBody);
        ugoClient.createEvaluationProject(createEvaluationProjectRequest);
    }

    private static Integer getEvaluationProjectId(UgoClient ugoClient, String evaluationProjectName) throws Exception {
        ListEvaluationProjectsRequest listEvaluationProjectsRequest = new ListEvaluationProjectsRequest();
        listEvaluationProjectsRequest.setEvaluationProjectName(evaluationProjectName);
        ListEvaluationProjectsResponse listEvaluationProjectsResponse = null;
        Integer totalCount = 0;
        for (int time = 0; time < 60; time++) {
            listEvaluationProjectsResponse = ugoClient.listEvaluationProjects(listEvaluationProjectsRequest);
            totalCount = listEvaluationProjectsResponse.getTotalCount();
            if (totalCount == 1) {
                break;
            }
            Thread.sleep(1000);
        }
        if (totalCount == 0) {
            logger.error("create evaluation project time out!");
            return null;
        }
        EvaluationProject evaluationProject = listEvaluationProjectsResponse.getEvaluationProjects().get(0);
        return evaluationProject.getEvaluationProjectId();
    }

    private static void checkEvaluationProjectStatus(UgoClient ugoClient, Integer evaluationProjectId) throws InterruptedException {
        ShowEvaluationProjectStatusRequest showEvaluationProjectStatusRequest = new ShowEvaluationProjectStatusRequest();
        showEvaluationProjectStatusRequest.setEvaluationProjectId(Integer.toString(evaluationProjectId));

        while (true) {
            ShowEvaluationProjectStatusResponse showEvaluationProjectStatusResponse
                    = ugoClient.showEvaluationProjectStatus(showEvaluationProjectStatusRequest);
            ShowEvaluationProjectStatusResponse.EvaluationProjectStatusEnum evaluationProjectStatus
                    = showEvaluationProjectStatusResponse.getEvaluationProjectStatus();
            ProjectStatusDetail projectStatusDetail = showEvaluationProjectStatusResponse.getProjectStatusDetail();
            String objectCollectionStatus = projectStatusDetail.getObjectCollectionStatus();
            String preMigrationStatus = projectStatusDetail.getPreMigrationStatus();
            String completedStatus = ShowEvaluationProjectStatusResponse.EvaluationProjectStatusEnum.COMPLETED.getValue();
            String pendingStatus = ShowEvaluationProjectStatusResponse.EvaluationProjectStatusEnum.PENDING.getValue();
            if (!completedStatus.equals(objectCollectionStatus)) {
                logger.info("object collection in progress: {}", projectStatusDetail.getObjectCollectionProgress());
                Thread.sleep(10000);
                continue;
            }
            if (!completedStatus.equals(preMigrationStatus)) {
                logger.info("pre-migration in progress: {}", projectStatusDetail.getPreMigrationProgress());
                Thread.sleep(10000);
                continue;
            }
            if (pendingStatus.equals(evaluationProjectStatus.getValue())) {
                logger.info("wait to confirm target db type.");
                break;
            }
        }
    }

    private static void confirmTargetDBType(UgoClient ugoClient, Integer evaluationProjectId, String targetDBType, String targetDBVersion) {
        ConfirmTargetDbTypeRequest confirmTargetDbTypeRequest = new ConfirmTargetDbTypeRequest();
        ConfirmTargetDBReq confirmTargetDBBody = new ConfirmTargetDBReq();
        confirmTargetDBBody.setEvaluationProjectId(Integer.toString(evaluationProjectId));
        confirmTargetDBBody.setTargetDbType(targetDBType);
        confirmTargetDBBody.setTargetDbVersion(targetDBVersion);
        confirmTargetDbTypeRequest.setBody(confirmTargetDBBody);
        ugoClient.confirmTargetDbType(confirmTargetDbTypeRequest);
    }

    private static void getEvaluationProjectDetail(UgoClient ugoClient, Integer evaluationProjectId) {
        ShowEvaluationProjectDetailRequest showEvaluationProjectDetailRequest = new ShowEvaluationProjectDetailRequest();
        showEvaluationProjectDetailRequest.setEvaluationProjectId(Integer.toString(evaluationProjectId));
        ugoClient.showEvaluationProjectDetail(showEvaluationProjectDetailRequest);
    }

    private static void deleteEvaluationProject(UgoClient ugoClient, Integer evaluationProjectId) {
        DeleteEvaluationProjectRequest deleteEvaluationProjectRequest = new DeleteEvaluationProjectRequest();
        deleteEvaluationProjectRequest.setEvaluationProjectId(Integer.toString(evaluationProjectId));
        ugoClient.deleteEvaluationProject(deleteEvaluationProjectRequest);
    }

}
